﻿#include "udpinterface.h"
#include <QFile>
#include <QByteArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QDebug>
#include <QtEndian>
#include <QThread>
#include <QNetworkDatagram>


using namespace Hydra_UDP;

UdpInterface::UdpInterface(QObject *parent) : QObject(parent)
{

}


UdpInterface::UdpInterface(QString path/*, QSocketDescriptor sock*/)
{    
    pSocket = new QUdpSocket(this);

    connect(pSocket, &QUdpSocket::readyRead, this, &UdpInterface::processReceivedMsg);

    init(path);
}


// 绑定网络
void UdpInterface::bindNet(NETWORK net)
{
    mNet = net;
    switch (net) {
    case NETWORK::J:
        if (QAbstractSocket::BoundState == pSocket->state()) {
            pSocket->close();
        }
        pSocket->bind(QHostAddress(mHmi.ip_J), mHmi.port_J, QUdpSocket::ShareAddress);
        break;

    case NETWORK::R:
        if (QAbstractSocket::BoundState == pSocket->state()) {
            pSocket->close();
        }
        pSocket->bind(QHostAddress(mHmi.ip_R), mHmi.port_R, QUdpSocket::ShareAddress);
        break;
    case NETWORK::INIT:
    default:
        break;
    }


}


// 设置通信周期
void UdpInterface::setCommunicationCycle(quint16 value)
{
    mTimer.setInterval(value);
}


// 获取连接状态
bool UdpInterface::getConnectState()
{
    return mConnectState;
}

// 设置主网络
void UdpInterface::setMainNet(bool value)
{
    mMainNet = value;
}

// 获取激活车头
CAB UdpInterface::getCab()
{
    return mCab;
}

// 设置预选模式
void UdpInterface::setPreMode(quint8 value)
{
    mPreMode = value;
}


// 接口初始化
void UdpInterface::init(QString path)
{
    readConfigFile(path);

    // 定期发送数据给ATP
    connect(&mTimer, &QTimer::timeout, this, &UdpInterface::sendMsgToATP);

    connect(&mTimer, &QTimer::timeout, &mConnectTimer, [&](){
        if (!mConnectTimer.isActive()) {
            mConnectTimer.start(DEFAULT_INTERVAL << 1);
        }
    });

    connect(&mConnectTimer, &QTimer::timeout, this, [&](){
        mConnectState = false;
    });

    connect(this, &UdpInterface::killConnectTimer, &mConnectTimer, [&](){
        mConnectTimer.stop();
    });


    mTimer.start(DEFAULT_INTERVAL);
}


// 读取配置文件
void UdpInterface::readConfigFile(QString path)
{
    QFile tConfig(path);

    if (!tConfig.open(QFile::ReadOnly)) {
        qDebug()<<"无法打开配置文件:" + path;
        return;
    }

    QByteArray tAllData = tConfig.readAll();
    tConfig.close();

    QJsonParseError tJsonError;
    QJsonDocument tJsonDoc(QJsonDocument::fromJson(tAllData, &tJsonError));

    if(tJsonError.error != QJsonParseError::NoError) {
        qDebug()<< "配置文件格式错误！";
        return;
    }

    QJsonObject tRootObj = tJsonDoc.object();


    // 获取HMI相关配置
    if (tRootObj.contains(QString("HMI"))) {
        if (1 == tRootObj.value("HMI").toObject().value("Cab").toInt())
        {
            mCab = CAB::A;
        }
        if (2 == tRootObj.value("HMI").toObject().value("Cab").toInt())
        {
            mCab = CAB::B;
        }

        mHmi.device_name = QString("HMI");
        mHmi.ip_J = tRootObj.value("HMI").toObject().value("IP_J").toString();
        mHmi.port_J = tRootObj.value("HMI").toObject().value("Port_J").toInt();
        mHmi.ip_R = tRootObj.value("HMI").toObject().value("IP_R").toString();
        mHmi.port_R = tRootObj.value("HMI").toObject().value("Port_R").toInt();
    }

    // 获取LocalATP相关配置
    if (tRootObj.contains(QString("LocalATP"))) {
        mLocalAtp.device_name = QString("LocalATP");
        mLocalAtp.ip_J = tRootObj.value("LocalATP").toObject().value("IP_J").toString();
        mLocalAtp.port_J = tRootObj.value("LocalATP").toObject().value("Port_J").toInt();
        mLocalAtp.ip_R = tRootObj.value("LocalATP").toObject().value("IP_R").toString();
        mLocalAtp.port_R = tRootObj.value("LocalATP").toObject().value("Port_R").toInt();
    }

    // 获取RemoteATP相关配置
    if (tRootObj.contains(QString("RemoteATP"))) {
        mRemoteAtp.device_name = QString("RemoteATP");
        mRemoteAtp.ip_J = tRootObj.value("RemoteATP").toObject().value("IP_J").toString();
        mRemoteAtp.port_J = tRootObj.value("RemoteATP").toObject().value("Port_J").toInt();
        mRemoteAtp.ip_R = tRootObj.value("RemoteATP").toObject().value("IP_R").toString();
        mRemoteAtp.port_R = tRootObj.value("RemoteATP").toObject().value("Port_R").toInt();
    }
}

// CRC8计算
quint8 UdpInterface::calCRC8(QByteArray bytes, quint8 poly)
{
    quint8 tCRC = 0x00;
    quint8 tData = 0x00;

    quint32 tLen = bytes.length();
    quint32 tPos = 0;

    do {
        tData = bytes.mid(tPos, 1).toHex().toUInt(NULL, 16);
        ++tPos;

        tCRC ^= tData;

        for (int i = 0; i < 8; ++i) {
            if (tCRC & 0x80) {
                tCRC = (tCRC << 1) ^ poly;
            }
            else {
                tCRC = tCRC << 1;
            }
        }
    }while(--tLen);
    return tCRC;
}




// 通过查表计算CRC8
quint8 UdpInterface::calCRC8FromCRC8Table(QByteArray bytes)
{
    quint8 tCRC = 0x00;
    quint8 tData = 0x00;

    quint32 tLen = bytes.length();
    quint32 tPos = 0;

    do {
        tData = bytes.mid(tPos, 1).toHex().toUInt(NULL, 16);
        ++tPos;

        tCRC = crc8_table[tCRC ^ tData];
    }while(--tLen);
    return tCRC;
}


// 通过传入指针的形式，查表计算CRC16
quint16 UdpInterface::calCRC16FromCRC16Table(unsigned char *buf, int len)
{
    int counter;
    unsigned char *p=buf;
    unsigned short crc = 0x0000;
    for( counter = 0; counter < len; ++counter)
    crc = (crc<<8) ^ crc16_table[((crc>>8) ^ ++*(char *)p)&0x00FF];
    return crc;
}

// 通过传入字节数组的形式，查表计算CRC16
quint16 UdpInterface::calCRC16FromCRC16Table(QByteArray byte)
{
    int counter;
    unsigned char *p=(unsigned char*)byte.data();
    unsigned short crc = 0x0000;
    for( counter = 0; counter < byte.size(); ++counter)
    crc = (crc<<8) ^ crc16_table[((crc>>8) ^ ++*(char *)p)&0x00FF];
    return crc;
}


// 处理发送数据报文头
void UdpInterface::addTRDPHeader(QByteArray *pByte)
{
    SEND_HEADER tHeader;

    switch (mCab) {
    case CAB::A:
        if (NETWORK::J == mNet) {
            tHeader.com_id = CAB_A_J_COMID;
        }
        if (NETWORK::R == mNet) {
            tHeader.com_id = CAB_A_R_COMID;
        }
        break;

    case CAB::B:
        if (NETWORK::J == mNet) {
            tHeader.com_id = CAB_B_J_COMID;
        }
        if (NETWORK::R == mNet) {
            tHeader.com_id = CAB_B_R_COMID;
        }
        break;

    case CAB::NONE:
    default:
        break;
    }

    tHeader.start_byte = qToBigEndian(tHeader.start_byte);
    tHeader.eth_id = qToBigEndian(tHeader.eth_id);
    tHeader.msg_len_hight = qToBigEndian(tHeader.msg_len_hight);
    tHeader.msg_len_low = qToBigEndian(tHeader.msg_len_low);
    tHeader.sequence_counter = qToBigEndian(mSendSequence);
    tHeader.protocol_version = qToBigEndian(tHeader.protocol_version);
    tHeader.com_id = qToBigEndian(tHeader.com_id);
    tHeader.etb_to_po_cnt = qToBigEndian(tHeader.etb_to_po_cnt);
    tHeader.op_trn_to_po_cnt = qToBigEndian(tHeader.op_trn_to_po_cnt);
    tHeader.data_length = qToBigEndian(tHeader.data_length);

    pByte->append(reinterpret_cast<char *>(&tHeader), sizeof(tHeader));

}


// 生成发送数据
void UdpInterface::addSendMsgData(QByteArray *pByte)
{
    SEND_MSG* tMsg = new SEND_MSG;
    QByteArray tTempByte;

    tMsg->sequence = mSendSequence;
    tMsg->mode_selected = mPreMode;

    mPreMode = 0;
    tTempByte.append(reinterpret_cast<char *>(tMsg), sizeof(SEND_MSG));

    tMsg->CRC = calCRC8FromCRC8Table(tTempByte.mid(0, sizeof(SEND_MSG) - 17));

    tTempByte.replace(sizeof(SEND_MSG) - 17, sizeof(tMsg->CRC), reinterpret_cast<char *>(&tMsg->CRC));

    *pByte += tTempByte;


    // 释放堆内存
    if (tMsg)
    {
        delete tMsg;
        tMsg = NULL;
    }
}


// 添加TRDP协议CRC16
void UdpInterface::addTRDPCRC16(QByteArray *pByte)
{
    quint16 tCRC = qToBigEndian(calCRC16FromCRC16Table(pByte->mid(4, pByte->size())));

    pByte->append(reinterpret_cast<char *>(&tCRC), sizeof(tCRC));
}



// 获取数据
void UdpInterface::processReceivedMsg()
{
    while(pSocket->hasPendingDatagrams()) {        

        QByteArray tData = pSocket->receiveDatagram().data();

        // 数据包长度是否有效校验
        if (sizeof(RECEIVED_HEADER) > (unsigned long long)tData.size()) {
            qDebug()<<"数据包长度校验失败";
            return;
        }


#ifdef DEBUG
        qDebug()<<"数据包长度是否有效校验通过";
#endif

        if (sizeof(RECEIVED_HEADER) < (unsigned long long)tData.size()) {
            // TRDP整体数据包长度校验
            RECEIVED_HEADER* pHeader = (RECEIVED_HEADER*)tData.data();
            if ((unsigned long long)((pHeader->msg_len_hight << 16) + pHeader->msg_len_low) != (unsigned long long)(tData.size() - 6)) {
                qDebug()<<"TRDP数据包长度校验失败";
                return;
            }
#ifdef DEBUG
            qDebug()<<"TRDP整体数据包长度校验通过";
#endif
            // TRDP应用字段长度校验
            if ((unsigned long long)(qToBigEndian(pHeader->data_length)) != (unsigned long long)(tData.size() - sizeof(RECEIVED_HEADER) - 2)) {
                qDebug()<<"TRDP应用字段长度校验失败";
                return;
            }
#ifdef DEBUG
            qDebug()<<"TRDP应用字段长度校验通过";
#endif
        }


//        if (sizeof(RECEIVED_HEADER) + sizeof(RECEIVED_MSG) != tData.size()) return;
        if (mMainNet && receivedMsgFlag) {
            emit sendReceivedData(tData);
            receivedMsgFlag = false;
        }

        mConnectState = true;

        if (mConnectTimer.isActive()) {
            emit killConnectTimer();
        }

        // CRC校验
//        if(tData.mid(tData.size() - 17, 1).toHex().toUInt(NULL, 16) == calCRC8FromCRC8Table(tData.mid(0, tData.size() - 17)))
//        {
//            mConnectState = true;

//            if (mMainNet) {
//                // 校验通过，将数据解析
//                RECEIVED_MSG* tMsg = (RECEIVED_MSG*)tData.data();

//                qDebug()<<tData;

//                // 数据压入队列
//                emit sendReceivedData(tData);

//                if (tMsg) {
//                    delete tMsg;
//                    tMsg = NULL;
//                }
//            }

//            if (mConnectTimer.isActive()) {
//                emit killConnectTimer();
//            }
//        }
//        else
//        {
//            mConnectState = false;
//            qDebug()<<"error code 0004";
//        }

    }
}

void UdpInterface::sendMsgToATP()
{
    QByteArray* tByte = new QByteArray;

    receivedMsgFlag = true;

    ++mSendSequence;
    addTRDPHeader(tByte);

    addSendMsgData(tByte);    

    addTRDPCRC16(tByte);

    // 发送到不同的网络
    switch (mNet) {
    case NETWORK::J: // 发送给J网
        pSocket->writeDatagram(*tByte, QHostAddress(mLocalAtp.ip_J), mLocalAtp.port_J);
        pSocket->writeDatagram(*tByte, QHostAddress(mRemoteAtp.ip_J), mRemoteAtp.port_J);
        break;

    case NETWORK::R: // 发送给R网
        pSocket->writeDatagram(*tByte, QHostAddress(mLocalAtp.ip_R), mLocalAtp.port_R);
        pSocket->writeDatagram(*tByte, QHostAddress(mRemoteAtp.ip_R), mRemoteAtp.port_R);
        break;

    case NETWORK::INIT:
    default:
        break;
    }


//    switch (mCab) {
//    case CAB::A:
//        // 发送到不同的网络
//        switch (mNet) {
//        case NETWORK::J: // 发送给J网
//            pSocket->writeDatagram(*tByte, QHostAddress(mLocalAtp.ip_J), mLocalAtp.port_J);
//            qDebug()<<"J cab a send to local" << mLocalAtp.ip_J << mLocalAtp.port_J;
//            qDebug()<<tByte->toHex();
//            break;
//        case NETWORK::R: // 发送给R网
//            pSocket->writeDatagram(*tByte, QHostAddress(mRemoteAtp.ip_R), mRemoteAtp.port_R);
//            qDebug()<<"R cab a send to remote" << mRemoteAtp.ip_J << mRemoteAtp.port_J;
//            qDebug()<<tByte->toHex();
//            break;
//        case NETWORK::INIT:
//        default:
//            break;
//        }
//        break;

//    case CAB::B:
//        // 发送到不同的网络
//        switch (mNet) {
//        case NETWORK::J: // 发送给J网
//            pSocket->writeDatagram(*tByte, QHostAddress(mRemoteAtp.ip_J), mRemoteAtp.port_J);
//            qDebug()<<"J cab b send to remote" << mRemoteAtp.ip_J << mRemoteAtp.port_J;
//            qDebug()<<tByte->toHex();
//            break;
//        case NETWORK::R: // 发送给R网
//            pSocket->writeDatagram(*tByte, QHostAddress(mLocalAtp.ip_R), mLocalAtp.port_R);
//            qDebug()<<"R cab b send to local" << mLocalAtp.ip_J << mLocalAtp.port_J;
//            qDebug()<<tByte->toHex();
//            break;
//        case NETWORK::INIT:
//        default:
//            break;
//        }
//        break;

//    case CAB::NONE:
//    default:
//        break;
//    }


    // 释放堆内存
    if (tByte)
    {
        tByte->clear();
        delete tByte;
        tByte = NULL;
    }

}




